Check for Perfect Number
Difficulty: Easy
Practice Links:
Problem Statement
You are given an integer n. You need to check if the number is a perfect number or not. Return true if it is a perfect number, otherwise, return false.
A perfect number is a number whose proper divisors (excluding the number itself) add up to the number itself.
Mathematical Definition
A positive integer n is perfect if: Sum of all proper divisors of n = n
Where proper divisors are all positive divisors of n except n itself.
Examples
Example 1:
Input: n = 6
Output: true
Explanation: Proper divisors of 6 are 1, 2, 3.
1 + 2 + 3 = 6.
Example 2:
Input: n = 4
Output: false
Explanation: Proper divisors of 4 are 1, 2.
1 + 2 = 3 ≠ 4.
Example 3:
Input: n = 28
Output: true
Explanation: Proper divisors of 28 are 1, 2, 4, 7, 14.
1 + 2 + 4 + 7 + 14 = 28.
Example 4:
Input: n = 1
Output: false
Explanation: 1 has no proper divisors (proper divisors exclude the number itself).
Example 5:
Input: n = 496
Output: true
Explanation: Proper divisors of 496 are 1, 2, 4, 8, 16, 31, 62, 124, 248.
Sum = 496.
Constraints
- 1 ≤ n ≤ 10^8
- n is a positive integer
Known Perfect Numbers
The first few perfect numbers are:
- 6 = 1 + 2 + 3
- 28 = 1 + 2 + 4 + 7 + 14
- 496 = 1 + 2 + 4 + 8 + 16 + 31 + 62 + 124 + 248
- 8128 = Sum of its proper divisors
- 33550336 = Sum of its proper divisors
Perfect numbers are extremely rare!
Key Concepts
- Proper Divisors: All positive divisors except the number itself
- Divisor Finding: Check if a number divides evenly (remainder = 0)
- Sum Accumulation: Add all found proper divisors
- Optimization: Use square root property to find divisors efficiently
Approach 1: Brute Force Solution
Algorithm / Intuition
The straightforward approach is to:
- Check all numbers from 1 to n-1 to find divisors
- Sum all proper divisors found
- Compare sum with original number
Core Logic:
- Iterate through all numbers from 1 to n-1
- For each number i, check if
n % i == 0(i is a divisor) - If i is a divisor, add it to the sum
- Finally, check if sum equals n
Step-by-Step Algorithm:
- Initialize
sum = 0to accumulate divisor sum - Loop from
i = 1toi = n-1(proper divisors only) - For each i, check if
n % i == 0 - If true, add i to sum
- After loop, return
sum == n
DryRun Example (Brute Force):
Input: n = 6
Initial: n = 6, sum = 0
i = 1: 6 % 1 = 0 → 1 is divisor → sum = 0 + 1 = 1
i = 2: 6 % 2 = 0 → 2 is divisor → sum = 1 + 2 = 3
i = 3: 6 % 3 = 0 → 3 is divisor → sum = 3 + 3 = 6
i = 4: 6 % 4 = 2 → not divisor
i = 5: 6 % 5 = 1 → not divisor
Final: sum = 6, n = 6
sum == n → true (6 is perfect)
Brute Force Code Solutions:
Java
class Solution {
public boolean isPerfect(int n) {
// Initialize sum to accumulate proper divisors
int sum = 0;
// Check all numbers from 1 to n-1 for divisors
for (int i = 1; i < n; i++) {
// If i divides n evenly, it's a proper divisor
if (n % i == 0) {
sum += i; // Add divisor to sum
}
}
// Check if sum of proper divisors equals the number
return sum == n;
}
}
JavaScript
class Solution {
isPerfect(n) {
// Initialize sum to accumulate proper divisors
let sum = 0;
// Check all numbers from 1 to n-1 for divisors
for (let i = 1; i < n; i++) {
// If i divides n evenly, it's a proper divisor
if (n % i == 0) {
sum += i; // Add divisor to sum
}
}
// Check if sum of proper divisors equals the number
return sum == n;
}
}
Python
class Solution:
def isPerfect(self, n):
# Initialize sum to accumulate proper divisors
sum = 0
# Check all numbers from 1 to n-1 for divisors using range(1, n)
for i in range(1, n):
# If i divides n evenly, it's a proper divisor
if n % i == 0:
sum += i # Add divisor to sum
# Check if sum of proper divisors equals the number
return sum == n
Brute Force Complexity:
- Time Complexity: O(n) - check all numbers from 1 to n-1
- Space Complexity: O(1) - constant extra space
Approach 2: Optimized Solution
Algorithm / Intuition
The key insight is that divisors come in pairs:
- If
iis a divisor ofn, thenn/iis also a divisor - We only need to check up to
√nto find all divisor pairs - This reduces time complexity from O(n) to O(√n)
Core Logic:
- Check divisors only up to √n
- For each divisor i found, also consider n/i
- Be careful not to double-count when i = n/i (perfect square case)
- Exclude n itself from the sum (proper divisors only)
Divisor Pairing Example:
For n = 28:
i = 1: divisors 1 and 28/1 = 28 → add 1 (exclude 28)
i = 2: divisors 2 and 28/2 = 14 → add both 2 and 14
i = 4: divisors 4 and 28/4 = 7 → add both 4 and 7
i = 7: already covered by i = 4
Proper divisors: 1, 2, 4, 7, 14
Sum: 1 + 2 + 4 + 7 + 14 = 28 ✓
Step-by-Step Algorithm:
- Handle edge case: if n = 1, return false (no proper divisors)
- Initialize
sum = 0 - Loop from
i = 1toi < √n - For each divisor i:
- Add i to sum
- If n/i ≠ n and i ≠ n/i, also add n/i to sum
- Return
sum == n
DryRun Example (Optimized):
Input: n = 28
Initial: n = 28, sum = 0, √28 ≈ 5.29
i = 1: 28 % 1 = 0 → divisor found
- Add i = 1 → sum = 1
- n/i = 28, but 28 = n, so don't add → sum = 1
i = 2: 28 % 2 = 0 → divisor found
- Add i = 2 → sum = 1 + 2 = 3
- n/i = 14, 14 ≠ 28 and 2 ≠ 14 → add 14 → sum = 3 + 14 = 17
i = 3: 28 % 3 = 1 → not divisor
i = 4: 28 % 4 = 0 → divisor found
- Add i = 4 → sum = 17 + 4 = 21
- n/i = 7, 7 ≠ 28 and 4 ≠ 7 → add 7 → sum = 21 + 7 = 28
i = 5: 5 ≥ √28, loop ends
Final: sum = 28, n = 28
sum == n → true (28 is perfect)
Optimized Code Solutions:
Java
class Solution {
public boolean isPerfect(int n) {
// Edge case: 1 has no proper divisors
if (n == 1) return false;
// Initialize sum to accumulate proper divisors
int sum = 0;
// Check divisors only up to √n for efficiency
for (int i = 1; i < Math.sqrt(n); i++) {
// If i divides n evenly, it's a divisor
if (n % i == 0) {
// Add the smaller divisor i
sum += i;
// Add the paired divisor n/i, but avoid double-counting and exclude n itself
if (n / i != n && i != n / i) {
sum = sum + (n / i);
}
}
}
// Check if sum of proper divisors equals the number
return sum == n;
}
}
JavaScript
class Solution {
isPerfect(n) {
// Edge case: 1 has no proper divisors
if (n == 1) return false;
// Initialize sum to accumulate proper divisors
let sum = 0;
// Check divisors only up to √n for efficiency
for (let i = 1; i < Math.sqrt(n); i++) {
// If i divides n evenly, it's a divisor
if (n % i == 0) {
// Add the smaller divisor i
sum += i;
// Add the paired divisor n/i, but avoid double-counting and exclude n itself
if (n / i != n && i != n / i) {
sum = sum + n / i;
}
}
}
// Check if sum of proper divisors equals the number
return sum == n;
}
}
Python
import math
class Solution:
def isPerfect(self, n):
# Edge case: 1 has no proper divisors
if n == 1:
return False
# Initialize sum to accumulate proper divisors
sum = 0
# Check divisors only up to √n for efficiency (range goes up to int(√n))
for i in range(1, int(math.sqrt(n)) + 1):
# If i divides n evenly, it's a divisor
if n % i == 0:
# Add the smaller divisor i
sum += i
# Add the paired divisor n//i, but avoid double-counting and exclude n itself
if n // i != n and i != n // i:
sum = sum + (n // i)
# Check if sum of proper divisors equals the number
return sum == n
Optimized Complexity:
- Time Complexity: O(√n) - check divisors only up to square root
- Space Complexity: O(1) - constant extra space
Complexity Analysis Summary
| Approach | Time Complexity | Space Complexity | Best For |
|---|---|---|---|
| Brute Force | O(n) | O(1) | Small numbers |
| Optimized | O(√n) | O(1) | Large numbers |
Edge Cases to Consider
- n = 1: No proper divisors → false
- n = 2: Proper divisor: 1, sum = 1 ≠ 2 → false
- Prime Numbers: Only proper divisor is 1 → sum = 1 ≠ n → false
- Perfect Squares: Be careful not to double-count √n when i = √n
- Large Perfect Numbers: 496, 8128, etc.
Detailed Edge Case Analysis
// Edge cases with step-by-step analysis
Input: 1 → Output: false (no proper divisors by definition)
Input: 2 → Output: false (proper divisors: 1, sum = 1 ≠ 2)
Input: 6 → Output: true (proper divisors: 1,2,3, sum = 6)
Input: 12 → Output: false (proper divisors: 1,2,3,4,6, sum = 16 ≠ 12)
Input: 28 → Output: true (proper divisors: 1,2,4,7,14, sum = 28)
Test Cases
public void testPerfectNumber() {
Solution sol = new Solution();
// Edge cases
assert sol.isPerfect(1) == false; // No proper divisors
assert sol.isPerfect(2) == false; // Prime number
// Perfect numbers
assert sol.isPerfect(6) == true; // First perfect number
assert sol.isPerfect(28) == true; // Second perfect number
assert sol.isPerfect(496) == true; // Third perfect number
assert sol.isPerfect(8128) == true; // Fourth perfect number
// Non-perfect numbers
assert sol.isPerfect(4) == false; // sum = 1+2 = 3
assert sol.isPerfect(12) == false; // sum = 1+2+3+4+6 = 16
assert sol.isPerfect(100) == false; // Not perfect
// Larger numbers
assert sol.isPerfect(33550336) == true; // Fifth perfect number
}
Step-by-Step Visualization
Brute Force Example: n = 6
Check all numbers 1 to 5:
i=1: 6%1=0 ✓ → sum = 0+1 = 1
i=2: 6%2=0 ✓ → sum = 1+2 = 3
i=3: 6%3=0 ✓ → sum = 3+3 = 6
i=4: 6%4=2 ✗ → skip
i=5: 6%5=1 ✗ → skip
Result: sum=6, n=6 → true
Optimized Example: n = 6
Check numbers 1 to √6 ≈ 2.45:
i=1: 6%1=0 ✓ → add 1, check 6/1=6 (=n, skip) → sum = 1
i=2: 6%2=0 ✓ → add 2, check 6/2=3 (≠n, ≠2, add) → sum = 1+2+3 = 6
Result: sum=6, n=6 → true
Mathematical Properties
1. Perfect Number Theorem
- Euclid-Euler Theorem: All even perfect numbers have the form 2^(p-1) × (2^p - 1) where 2^p - 1 is prime
- Unknown: Whether odd perfect numbers exist (major unsolved problem)
2. Perfect Number Characteristics
- All known perfect numbers are even
- Perfect numbers end in 6 or 28 (except 6 itself)
- Extremely rare: only 51 perfect numbers known as of 2018
3. Related Concepts
- Abundant Numbers: Sum of proper divisors > n
- Deficient Numbers: Sum of proper divisors < n
- Amicable Numbers: Pairs where each equals sum of other's proper divisors
Common Mistakes to Avoid
- Including n in sum: Perfect numbers use proper divisors (excluding n itself)
- Double-counting in optimization: When i = n/i, don't add the same divisor twice
- Wrong square root handling: Use
i < √n, noti <= √nto avoid edge cases - Integer division errors: In Python, use
//for integer division - Forgetting edge case: n = 1 has no proper divisors
Optimization Techniques
1. Early Termination
// If sum already exceeds n, it can't be perfect
if (sum > n) return false;
2. Mathematical Shortcuts
// Check if n is of the form 2^(p-1) × (2^p - 1)
// This covers all known even perfect numbers
3. Precomputed Perfect Numbers
// For contest/interview scenarios
private static final Set<Integer> PERFECT_NUMBERS =
Set.of(6, 28, 496, 8128, 33550336);
public boolean isPerfect(int n) {
return PERFECT_NUMBERS.contains(n);
}
Performance Comparison
Time Complexity Comparison:
For n = 1,000,000:
- Brute Force: 1,000,000 operations
- Optimized: ~1,000 operations (√1,000,000 = 1,000)
- Speedup: 1000x faster!
Key Learning Points
- Divisor Properties: Understanding how divisors come in pairs
- Square Root Optimization: Fundamental technique for divisor problems
- Edge Case Handling: Proper divisors exclude the number itself
- Mathematical Definitions: Converting number theory concepts to code
- Algorithm Optimization: Trading slight complexity for major performance gains
Related Problems
- Sum of Divisors: Calculate sum of all divisors (including n)
- Count Divisors: Count total number of divisors
- Abundant Numbers: Check if sum of proper divisors > n
- Amicable Numbers: Find pairs of numbers that are "friends"
- Deficient Numbers: Check if sum of proper divisors < n
- Aliquot Sequences: Iterative sum of proper divisors
Real-World Applications
- Number Theory Research: Study of perfect and related number types
- Mathematical Education: Teaching divisibility and number properties
- Algorithm Design: Demonstrating optimization techniques
- Recreational Mathematics: Puzzles and mathematical curiosities
- Computer Science: Understanding time complexity trade-offs
Follow-up Questions
- How would you find all perfect numbers up to a given limit?
- Can you modify this to find abundant or deficient numbers?
- How would you handle very large numbers efficiently?
- What's the relationship between perfect numbers and Mersenne primes?
- How would you implement this using only recursion?
Summary
The perfect number problem demonstrates:
- Mathematical property verification through computational methods
- Algorithm optimization using mathematical insights (divisor pairing)
- Edge case handling in number theory problems
- Trade-offs between simplicity and efficiency
Brute Force: O(n) time, simple but slow
Optimized: O(√n) time, more complex but much faster
Key Insight: Divisors come in pairs, so we only need to check up to √n
This problem serves as an excellent introduction to divisor-based algorithms and demonstrates how mathematical insights can lead to significant performance improvements. The optimization from O(n) to O(√n) is a fundamental technique used in many number theory problems.